/**
 * Copyright ©2012-2018 HopeHaiyang Corporation, All Rights Reserved
 * http://www.wuhanhope.com
 */
package hope.platform.data.event;

import hope.platform.data.domain.HopeException;
import hope.platform.data.domain.HopeExceptionKind;
import hope.platform.data.domain.Warning;
import hope.platform.data.server.event.header.WarningListenerService;
import hope.platform.data.server.remote.ObservedService;
import hope.platform.data.server.data.header.HopeExceptionKindService;
import hope.platform.data.server.data.header.HopeExceptionService;
import hope.platform.data.server.data.header.WarningService;
import hope.platform.data.utils.TimeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * class info
 *
 * @author hujia
 *         Create at 2018/7/24 11:21
 */
@Component
public class ExceptionListener  {

    @Autowired
    private HopeExceptionKindService exceptionKindService;
    @Autowired
    private WarningService warningService;
    @Autowired
    private HopeExceptionService exceptionService;
    @Autowired
    private WarningListenerService warningListenerService;
    @Autowired
    private ObservedService observedService;

    @Async
    @EventListener
    public void listenerEvent(ExceptionEvent exceptionEvent) {
        exceptionWarning(exceptionEvent);
    }

    public void exceptionWarning(ExceptionEvent exceptionEvent) {
        //查询触发告警条件。
        //满足条件发布告警事件
        HopeExceptionKind exceptionKind = exceptionKindService.getByExceptionType(
                exceptionEvent.getHopeException().getExceptionType());
        if (exceptionKind.getTriggerMethod().getAccumulateCount() != 0) {
            accumulateMethod(exceptionEvent, exceptionKind);
        } else if (exceptionKind.getTriggerMethod().getContinuousCount() != 0) {
            continuousMethod(exceptionEvent, exceptionKind);
        } else {
            informWarningEvent(exceptionEvent.getHopeException().getSerialNumber(),
                    exceptionEvent.getHopeException().getDataName(),
                    exceptionKind.getWarningType(),
                    exceptionEvent.getHopeException().getContent());
        }
    }

    private void continuousMethod(ExceptionEvent exceptionEvent, HopeExceptionKind exceptionKind) {
        Date now = new Date();
        String serialNumber = exceptionEvent.getHopeException().getSerialNumber();
        String dataName = exceptionEvent.getHopeException().getDataName();
        int count = exceptionKind.getTriggerMethod().getContinuousCount();
        Date beginTime = TimeUtils.getBeforeTime(now, exceptionKind.getTriggerMethod().getContinuousMinutes());
        //查询异常表结果5条
        List<HopeException> exceptions = exceptionService.
                getBySerialNumberAndDataNameAndGmtCreateBetweenOrderByGmtCreateDesc(
                        serialNumber, dataName, beginTime, now);
        if (exceptions.size() >= count - 1) {
            //选取第倒数第一条数据
            beginTime = exceptions.get(exceptions.size() -1 ).getGmtCreate();
            //查询数据库中的记录。
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            int countResult = observedService.countResult(serialNumber, dataName,
                    sdf.format(beginTime), sdf.format(now));
            //如果没有表明连续，如果有表明不连续
            if (countResult == 0) {
                informWarningEvent(serialNumber, dataName, exceptionKind.getWarningType(),
                        exceptionEvent.getHopeException().getContent());
            }
        }
    }

    private void accumulateMethod(ExceptionEvent exceptionEvent, HopeExceptionKind exceptionKind) {
        Date now = new Date();
        String serialNumber = exceptionEvent.getHopeException().getSerialNumber();
        String dataName = exceptionEvent.getHopeException().getDataName();
        Date beginTime = TimeUtils.getBeforeTime(now, exceptionKind.getTriggerMethod().getAccumulateMinutes());
        //查询该类别异常信息发警报的上次信息
        Warning warning = warningService.getTopBySerialNumberAndDataNameOrderByGmtCreateDesc(
                serialNumber, dataName);
        if (null != warning && warning.getGmtCreate().after(beginTime)) {
            beginTime = warning.getGmtCreate();
        }
        //查询累计次数是否有超过设定值
        long countResult = exceptionService.countBySerialNumberAndDataNameAndGmtCreateBetween(
                serialNumber, dataName,  beginTime, now);
        //判断是否触发告警条件
        if (countResult >= exceptionKind.getTriggerMethod().getAccumulateCount()) {
            informWarningEvent(serialNumber, dataName, exceptionKind.getWarningType(),
                    exceptionEvent.getHopeException().getContent());
        }
    }


    private void informWarningEvent(String serialNumber, String dataName, String warningType, String content) {
        //通知告警事件
        Warning tmp = new Warning();
        tmp.setSerialNumber(serialNumber);
        tmp.setDataName(dataName);
        tmp.setWarningType(warningType);
        tmp.setContent(content);
        warningListenerService.publish(tmp);
    }
}
